/**
* @file ajax.js.
* @author liaoxuezhi@baidu.com
*/
/* eslint-disable */

import * as axios from 'axios';
import * as assign from 'object-assign';

import {
  ValidationError,
  CSRFError,
  SessionExpiredError
} from './errors';
const rSchema = /^(get|post|put|delete):/i;
let adpater = null;

export function setAdapter(_) {
  adpater = _;
}


function returnSuccess(response, url) {
  if (response && response.headers && response.headers['content-disposition']) {
    const disposition = response.headers['content-disposition'];
    let filename = '';
    if (disposition && disposition.indexOf('attachment') !== -1) {
      let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
      let matches = filenameRegex.exec(disposition);
      if (matches != null && matches[1]) {
        filename = matches[1].replace(/['"]/g, '')
      };
      let type = response.headers['content-type'];
      let blob = new Blob([response.data], { type: type });
      if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
        window.navigator.msSaveBlob(blob, filename);
      } else {
        let URL = window.URL || window.webkitURL;
        let downloadUrl = URL.createObjectURL(blob);
        if (filename) {
          // use HTML5 a[download] attribute to specify filename
          let a = document.createElement("a");
          // safari doesn't support this yet
          if (typeof a.download === 'undefined') {
            window.location = downloadUrl;
          } else {
            a.href = downloadUrl;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
          }
        } else {
          window.location = downloadUrl;
        }
        setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
      }
    }
    return;
  }
  
  let _response = null;
  adpater && (_response = new Function('response', 'api', adpater)(response.data, url));

  if (_response) {
    response.data = _response;
  }
  if (!response.data) {
    throw new Error('未返回数据');
  }

  if (response.data.hasOwnProperty('error_code')) {
    response.data.status = response.data.error_code;
    response.data.msg = response.data.error_message;
  }

  if (!response.data.hasOwnProperty('status') || response.data.status !== 0) {
    return returnFail(response, url);
  }
  return response.data;
}

function returnFail(response, url) {
  let _response = null;

  adpater && !(response instanceof Error) && (_response = new Function('response', 'api', adpater)(response.data, url));

  if (_response) {
    response.data = _response;
  }

  if (response instanceof Error) {
    throw response;
  } else if (response.data && response.data.status === 302) {
    location.href = response.data.url;
    throw new SessionExpiredError(response.data.msg || '您已退出登陆，请重新登陆');
  } else if (response.status === 422 || response.data && response.data.status === 422) {
    throw new ValidationError(response.data.msg || '表单验证失败, 请检查字段',
    response.data.data && response.data.data.errors || response.data.errors);
  } else if (response.data && response.data.msg && ~response.data.msg.indexOf('CSRF')) {
    setTimeout(() => location.reload(), 3000);
    throw new CSRFError('由于您长期没有操作,会话已经失效,请刷新页面');
  } else if (response.data) {
    throw new Error(response.data.msg || 'API调用错误');
  } else {
    // that falls out of the range of 2xx
    let error = response.statusText || 'Unknown error';
    if (typeof response.data === 'string') {
      error = response.data;
    } else if (response.data && response.data.msg) {
      error = response.data.msg;
    }

    throw new Error(error);
  }
}

export function get(url, config = {}) {
  config.withCredentials = true;
  config.headers = {'X-Requested-With': 'XMLHttpRequest'};
  return axios.get(url, config)
  .then(response => returnSuccess(response, url))
  .catch(response => returnFail(response, url));
}

export function post(url, data, config = {}) {
  config.withCredentials = true;
  config.headers = {'X-Requested-With': 'XMLHttpRequest'};

  return axios.post(url, data, config)
  .then(response => returnSuccess(response, url))
  .catch(response => returnFail(response, url));
}

export function put(url, data, config = {}) {
  config.withCredentials = true;
  config.params = config.params || {};
  config.params._method = 'put';
  config.headers = {'X-Requested-With': 'XMLHttpRequest'};

  return axios.put(url, data, config)
  .then(response => returnSuccess(response, url))
  .catch(response => returnFail(response, url));
}

export function remove(url, config = {}) {
  config.withCredentials = true;
  config.params = config.params || {};
  config.params._method = 'delete';
  config.headers = {'X-Requested-With': 'XMLHttpRequest'};

  return axios.post(url, null, config)
  .then(response => returnSuccess(response, url))
  .catch(response => returnFail(response, url));
}

export function patch(url, data, config = {}) {
  config.withCredentials = true;
  config.params = config.params || {};
  config.params._method = 'patch';
  config.headers = {'X-Requested-With': 'XMLHttpRequest'};

  return axios.post(url, data, config)
  .then(response => returnSuccess(response, url))
  .catch(response => returnFail(response, url));
}
